package src

import (
    "fmt"
    "time"
)

type Universe [][]bool

const (
    width  = 80
    height = 15
)

func NewUniverse() Universe {
    // Done: 使用make分配并返回一个height行width列的Universe, 并所有元素均为false
    u := make([][]bool, height)
    for row := 0; row < len(u); row++ {
        u[row] = make([]bool, width)
    }

    return u
}

func (u Universe) Show() {
    // Done: 存活细胞用*号表示, 死亡细胞用空格表示，使用fmt打印出来
    for _, row := range u {
        for _, v := range row {
            switch v {
            case true:
                fmt.Print("*")
            default:
                fmt.Print(" ")
            }
        }
        fmt.Println("|")
    }
}

func (u Universe) Seed() {
    // Done: 随机激活25%的细胞
    result := RandomWakeUp()

    for i := 0; i < len(result); i++ {
        posY := result[i] / width
        posX := result[i]%width - 1

        if posX == -1 {
            posX = width - 1
        }
        u[posY][posX] = true
    }
}

func (u Universe) alive(x, y int) bool {
    /* Done: 需要实现世界回绕
     * 1. 当邻近存活数<2||>3, 细胞死亡
     * 2. 当邻近存活数==2, 维持原样
     * 3. 当邻近存活数==3, 细胞复生
     **/
    aliveCount := u.neighbors(x, y)

    var isAlive bool
    switch {
    case aliveCount < 2 || aliveCount > 3:
        isAlive = false
    case aliveCount == 3:
        isAlive = true
    default:
        isAlive = u[y][x]
    }
    return isAlive
}

func (u Universe) neighbors(x, y int) int {
    // Done: 统计邻近存活细胞数, 指定细胞不计入
    up := y - 1
    down := y + 1
    left := x - 1
    right := x + 1

    switch {
    case up < 0:
        up = height - 1
        fallthrough
    case down == height:
        down = 0
        fallthrough
    case left < 0:
        left = width - 1
        fallthrough
    case right == width:
        right = 0
    }

    north := u[up][x]
    south := u[down][x]
    west := u[y][left]
    east := u[y][right]
    northEast := u[up][right]
    northWest := u[up][left]
    southEast := u[down][right]
    southWest := u[down][left]

    aliveSlice := [8]bool{north, south, west, east, northEast, northWest, southEast, southWest}
    aliveCount := 0
    for _, v := range aliveSlice {
        if v {
            aliveCount++
        }
    }
    return aliveCount
}

func (u Universe) Next() Universe {
    // Done: 得出下一个世代存活的元素
    nextUniverse := NewUniverse()

    for row := 0; row < len(u); row++ {
        for col := 0; col < len(u[row]); col++ {
            nextUniverse[row][col] = u.alive(col, row)
        }
    }
    return nextUniverse
}

func Step(a, b Universe) {
    // Done: 平行世界
    time.Sleep(time.Second / 4)
    ClearScreen()

    a, _ = b, a
    a.Show()

    Step(a, a.Next())
}
